package com.achievo.know.application.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.apache.struts2.json.JSONException;
import org.apache.struts2.json.JSONUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.achievo.know.application.AuthApplication;
import com.achievo.know.domain.Category;
import com.achievo.know.domain.CategoryRepository;
import com.achievo.know.domain.Function;
import com.achievo.know.domain.FunctionRepository;
import com.achievo.know.domain.Role;
import com.achievo.know.domain.RoleRepository;
import com.achievo.know.domain.User;
import com.achievo.know.domain.UserRepository;
import com.achievo.know.domain.Role.Status;
import com.achievo.know.pojo.JsonCategory;
import com.achievo.know.pojo.JsonFunction;
import com.achievo.know.pojo.JsonRole;
import com.achievo.know.pojo.RoleInit;
import com.achievo.know.pojo.SearchParam;
import com.dayatang.querychannel.service.QueryChannelService;
import com.dayatang.querychannel.support.Page;

@Service
public class AuthApplicationImpl implements AuthApplication {

	@Autowired
	private QueryChannelService queryChannel;
	@Autowired
	private RoleRepository roleRepository;
	@Autowired
	private UserRepository userRepository;
	@Autowired
	private FunctionRepository functionRepository;
	@Autowired
	private CategoryRepository categoryRepository;

	public FunctionRepository getFunctionRepository() {
		return functionRepository;
	}

	public void setFunctionRepository(FunctionRepository functionRepository) {
		this.functionRepository = functionRepository;
	}

	public UserRepository getUserRepository() {
		return userRepository;
	}

	public void setUserRepository(UserRepository userRepository) {
		this.userRepository = userRepository;
	}

	public RoleRepository getRoleRepository() {
		return roleRepository;
	}

	public void setRoleRepository(RoleRepository roleRepository) {
		this.roleRepository = roleRepository;
	}

	public QueryChannelService getQueryChannel() {
		return queryChannel;
	}

	public void setQueryChannel(QueryChannelService queryChannel) {
		this.queryChannel = queryChannel;
	}

	@Override
	@Transactional
	public void batchDeleteRole(String[] ids) {
		roleRepository.batchDelete(ids);
	}

	@Override
	@Transactional
	public void batchDeleteUser(String[] ids) {
		userRepository.batchDelete(ids);
	}

	@Override
	@Transactional
	public void batchSetFunction(String roleId, String[] funcIds) {
		Role r = roleRepository.get(Long.parseLong(roleId));
		Set<Function> functions = new HashSet<Function>();
		Map<Long,Function> mapFunc=new HashMap<Long,Function>();
		for (String fid : funcIds) {
			if("999".equals(fid))//虚拟的根目录，不用持久化
				continue;
			Function f = functionRepository.get(Long.parseLong(fid));
			if(!mapFunc.containsKey(f.getId()))
				mapFunc.put(f.getId(), f);
			Function parent=f.getParent();
			if(parent!=null){
				if(!mapFunc.containsKey(parent.getId()))
					mapFunc.put(parent.getId(), parent);
			}
		}
		Collection<Function> ss=mapFunc.values();
		for(Function s:ss){
			functions.add(s);
		}
		r.authorize(functions);

	}

	@Override
	@Transactional
	public void batchSetRole(String userId, String[] roleIds) {
		User user = userRepository.get(Long.parseLong(userId));
		Set<Role> roles = new HashSet<Role>();
		for (String rid : roleIds) {
			if("999".equals(rid))
				continue;
			Role r = roleRepository.get(Long.parseLong(rid));
			roles.add(r);
		}
		user.setRoles(roles);
		userRepository.save(user);
	}

	@Override
	public Page<Role> queryRolePage(int currentPage, int pageSize) {
		String hql = "from Role r order by r.id  ";
		Object[] params = new Object[] {};
		return queryChannel.queryPagedResultByPageNo(hql, params, currentPage,
				pageSize);
	}

	@Override
	public Page<User> queryUserPage(int currentPage, int pageSize, SearchParam params) {
		StringBuilder hql=new StringBuilder();
		hql.append("select u from User u ");
		List<Object> pl=new ArrayList<Object>();
		if(params!=null){
			if(StringUtils.isNotEmpty(params.getRoleName()) && !"-1".equals(params.getRoleName())){
				//Role r=roleRepository.get(Long.parseLong(params.getRoleName()));
				hql.append(" inner join u.roles as role where role.id=?");
				pl.add(Long.parseLong(params.getRoleName()));
			}else{
				hql.append(" where 1=1 ");
			}
			if(StringUtils.isNotEmpty(params.getDept())){
				hql.append(" and u.deptment like ?");
				pl.add("%"+params.getDept()+"%");
			}
			if(StringUtils.isNotEmpty(params.getUsername())){
				hql.append(" and u.username like ?");
				pl.add("%"+params.getUsername()+"%");
			}
			hql.append(" and u.locked = ?");
			pl.add(false);
		}else{
			hql.append(" and u.locked = ?");
			pl.add(false);
		}
		hql.append(" order by u.id  ");
		return queryChannel.queryPagedResultByPageNo(hql.toString(), pl.toArray(), currentPage,
				pageSize);
	}

	@Override
	@Transactional
	public void saveRole(Role role) {
		if (role.getId() != null) {
			role.update();
		} else {// add new
			role.setStatus(Status.ENABLED);
			role.create();
		}

	}

	@Override
	@Transactional
	public void saveUser(User user) {
		if (user.getId() != null) {
			if (!user.isLocal()) {
				throw new RuntimeException("不能更改该用户");
			}
			User u = userRepository.get(user.getId());
			u.setUsername(user.getUsername());
			if (User.isUsernameExist(user.getUsername())
					&& (!u.getUsername().equals(user.getUsername()))) {
				throw new RuntimeException("已经存在该用户名");
			}
			userRepository.save(u);
		} else {// add new
			user.setLocal(true);
			user.setLocked(false);
			user.setRegistryDate(new Date());
			if (User.isUsernameExist(user.getUsername())) {
				throw new RuntimeException("已经存在该用户名");
			}
			/*Role emp = roleRepository.get(RoleInit.EMP);
			Set<Role> roles = new HashSet<Role>();
			roles.add(emp);
			user.setRoles(roles);*/
			userRepository.save(user);
			userRepository.addRole(user.getId(),RoleInit.EMP);
		}

	}

	@Override
	@Transactional
	public void setCategorys(String userId, String[] cateIds) {
		User user = userRepository.get(Long.parseLong(userId));
		Set<Category> cates = new HashSet<Category>();
		Map<Long,Category> mapFunc=new HashMap<Long,Category>();
		for (String cid : cateIds) {
			if("999".equals(cid))
				continue;
			if(StringUtils.isEmpty(cid))
				continue;
			Category r = categoryRepository.get(Long.parseLong(cid));
			if(!mapFunc.containsKey(r.getId()))
				mapFunc.put(r.getId(), r);
			setParent(mapFunc, r);
		}
		Collection<Category> ss=mapFunc.values();
		for(Category s:ss){
			cates.add(s);
		}
		user.setCategorys(cates);
		userRepository.save(user);

	}

	private void setParent(Map<Long, Category> mapFunc, Category r) {
		if(r!=null){
			Category parent=r.getParent();
			if(parent!=null){
				if(!mapFunc.containsKey(parent.getId())){
					mapFunc.put(parent.getId(), parent);
					setParent(mapFunc, parent);
				}
			}
		}
	}
	
	@Override
	@Transactional
	public void setRoleCategorys(String roleId, String[] cateIds) {
		Role role=roleRepository.get(Long.parseLong(roleId));
		Set<Category> cates = new HashSet<Category>();
		Map<Long,Category> mapFunc=new HashMap<Long,Category>();
		for (String cid : cateIds) {
			if("999".equals(cid))
				continue;
			Category r = categoryRepository.get(Long.parseLong(cid));
			if(!mapFunc.containsKey(r.getId()))
				mapFunc.put(r.getId(), r);
			//Category parent=r.getParent();
			setParent(mapFunc, r);
		}
		Collection<Category> ss=mapFunc.values();
		for(Category s:ss){
			cates.add(s);
		}
		role.setCategorys(cates);
		roleRepository.save(role);
		
	}

	@Override
	public List<Role> getRoles() {
		return roleRepository.getAll();
	}

	
	@Override
	@Transactional
	public void changePwd(String username, String password) {
		User u=userRepository.get(username);
		u.setPassword(password);
		userRepository.save(u);
	}

	@Override
	public Role getRole(Long id) {
		return roleRepository.get(id);
	}

	@Override
	public User getUser(Long id) {
		return userRepository.get(id);
	}
	
	private boolean isIn(Set<Function> fs,Long fid){
		if(fs==null)
			return false;
		for(Function f:fs){
			if(fid.longValue()==f.getId().longValue())
				return true;
		}
		return false;
	}

	@Override
	public String getFuncJson(Long roleId) {
		Role role=roleRepository.get(roleId);
		Set<Function> fs=null;
		if(role!=null)
			fs=role.getFunctions();
		List<JsonFunction> emptyAllRoot = new ArrayList<JsonFunction>();
		JsonFunction emptyRoot=new JsonFunction();
		emptyRoot.setId(999L);
		emptyRoot.setText("根");
		List<JsonFunction> AllRoot = new ArrayList<JsonFunction>();

		List<Function> roots = getRootFuncs();
		for (Function root : roots) {// 一级
			JsonFunction croot = new JsonFunction();
			croot.setText(root.getAlias());
			croot.setId(root.getId());
			if(isIn(fs, root.getId()))
				croot.setIschecked(true);
			List<Function> children = root.getChildren();
			if (children.size() > 0) {
				List<JsonFunction> l12 = new ArrayList<JsonFunction>();
				for (Function child : children) {// 二级
					JsonFunction cchild = new JsonFunction();
					cchild.setText(child.getAlias());
					cchild.setId(child.getId());
					if(isIn(fs, child.getId()))
						cchild.setIschecked(true);
					List<Function> children1 = child.getChildren();
					if (children1.size() > 0) {
						List<JsonFunction> l121 = new ArrayList<JsonFunction>();
						for (Function child1 : children1) {// 三级
							JsonFunction cchild1 = new JsonFunction();
							cchild1.setText(child1.getAlias());
							cchild1.setId(child1.getId());
							if(isIn(fs, child1.getId()))
								cchild1.setIschecked(true);
							l121.add(cchild1);
						}
						cchild.setChildren(l121);
					}
					l12.add(cchild);
				}
				croot.setChildren(l12);
			}
			AllRoot.add(croot);
		}
		emptyRoot.setChildren(AllRoot);
		emptyAllRoot.add(emptyRoot);
		try {
			return JSONUtil.serialize(emptyAllRoot, null, null, false, true);
		} catch (JSONException e) {
			return "";
		}
	}

	@Override
	public String getRolesJson(Long userId) {
		User user=userRepository.get(userId);
		Set<Role> rs=null;
		if(user!=null)
			rs=user.getRoles();
		List<JsonRole> emptyAllRoot = new ArrayList<JsonRole>();
		JsonRole emptyRoot=new JsonRole();
		emptyRoot.setId(999L);
		emptyRoot.setText("根");
		List<JsonRole> AllRoot = new ArrayList<JsonRole>();

		List<Role> roots = roleRepository.getAll();
		for (Role root : roots) {
			JsonRole croot = new JsonRole();
			croot.setText(root.getName());
			croot.setId(root.getId());
			if(isRoleIn(rs, root.getId()))
				croot.setIschecked(true);
			AllRoot.add(croot);
		}
		emptyRoot.setChildren(AllRoot);
		emptyAllRoot.add(emptyRoot);
		try {
			return JSONUtil.serialize(emptyAllRoot, null, null, false, true);
		} catch (JSONException e) {
			return "";
		}
	}

	@Override
	public String getCatesJson(Long userId) {
		User user=userRepository.get(userId);
		Set<Category> cs=null;
		if(user!=null)
			cs=user.getCategorys();
		List<JsonCategory> emptyAllRoot = new ArrayList<JsonCategory>();
		JsonCategory emptyRoot=new JsonCategory();
		emptyRoot.setId(999L);
		emptyRoot.setText("根");
		emptyRoot.setIsexpand(true);
		List<JsonCategory> AllRoot = new ArrayList<JsonCategory>();
		
		List<Category> roots = categoryRepository.getRoots();
		for (Category root : roots) {// 一级
			create(cs, AllRoot, root,emptyRoot);
		}
		emptyRoot.setChildren(AllRoot);
		emptyAllRoot.add(emptyRoot);
		try {
			return JSONUtil.serialize(emptyAllRoot, null, null, false, true);
		} catch (JSONException e) {
			return "";
		}
	}

	private void create(Set<Category> cs, List<JsonCategory> AllRoot,
			Category root,JsonCategory emptyRoot) {
		JsonCategory croot = new JsonCategory();
		croot.setText(root.getName());
		croot.setId(root.getId());
		if(isCateIn(cs, root.getId())){
			croot.setIschecked(true);
			emptyRoot.setIschecked(true);
		}
		List<Category> children = root.getChildren();
		if (children.size() > 0) {
			List<JsonCategory> l12 = new ArrayList<JsonCategory>();
			for (Category child : children) {// 二级
				/*JsonCategory cchild = new JsonCategory();
				cchild.setText(child.getName());
				cchild.setId(child.getId());
				if(isCateIn(cs, child.getId()))
					cchild.setIschecked(true);
				l12.add(cchild);*/
				create(cs,l12,child,emptyRoot);
			}
			croot.setChildren(l12);
		}
		AllRoot.add(croot);
	}
	
	@Override
	public String getRoleCatesJson(Long id) {
		Role role=roleRepository.get(id);
		Set<Category> cs=null;
		if(role!=null)
			cs=role.getCategorys();
		List<JsonCategory> emptyAllRoot = new ArrayList<JsonCategory>();
		JsonCategory emptyRoot=new JsonCategory();
		emptyRoot.setId(999L);
		emptyRoot.setText("根");
		emptyRoot.setIsexpand(true);
		List<JsonCategory> AllRoot = new ArrayList<JsonCategory>();

		List<Category> roots = categoryRepository.getRoots();
		for (Category root : roots) {// 一级
			create(cs, AllRoot, root,emptyRoot);
		}
		emptyRoot.setChildren(AllRoot);
		emptyAllRoot.add(emptyRoot);
		try {
			return JSONUtil.serialize(emptyAllRoot, null, null, false, true);
		} catch (JSONException e) {
			return "";
		}
	}

	private boolean isCateIn(Set<Category> cs, Long id) {
		if(cs==null)
			return false;
		for(Category f:cs){
			if(id.longValue()==f.getId().longValue())
				return true;
		}
		return false;
	}

	private boolean isRoleIn(Set<Role> rs, Long id) {
		if(rs==null)
			return false;
		for(Role f:rs){
			if(id.longValue()==f.getId().longValue())
				return true;
		}
		return false;
	}

	public List<Function> getRootFuncs() {
		return functionRepository.getRootFuncs();
	}

}
